package com.zhangtai.modules.service.impl.qw;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.rabbitmq.client.Return;
import com.zhangtai.modules.dao.QwCheckRuleDao;
import com.zhangtai.modules.dao.QwCheckinMonthDao;
import com.zhangtai.modules.dao.QwCheckinsDao;
import com.zhangtai.modules.dao.QwUserDao;
import com.zhangtai.modules.dto.ExportQwCheckMonthTableDto;
import com.zhangtai.modules.entity.qw.QwCheckRuleEntity;
import com.zhangtai.modules.entity.qw.QwCheckinsEntity;
import com.zhangtai.modules.jobTask.qw.QwUserEntity;
import com.zhangtai.modules.service.qw.QwCheckinsService;
import com.zhangtai.modules.vo.CheckRecord;
import com.zhangtai.utils.PageUtils;
import com.zhangtai.utils.Query;
import com.zhangtai.utils.StringUtils;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.web.client.RestTemplate;

@ConfigurationProperties(prefix = "qw.check")
@Data
@Service("qwCheckinsService")
public class QwCheckinsServiceImpl extends ServiceImpl<QwCheckinsDao, QwCheckinsEntity> implements QwCheckinsService {
    @Autowired
    private QwCheckinsDao qwCheckinsDao;
    @Autowired
    private QwUserDao qwUserDao;
    @Autowired
    private QwCheckRuleDao qwCheckRuleDao;
    @Autowired
    private QwCheckinMonthDao qwCheckinMonthDao;
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    private RestTemplate restTemplate;

    private String corpid;
    private String corpsecret;

    //获取考勤的TOKEN
    public String getCheckToktn() {
        JSONObject forObject = restTemplate.getForObject("https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=" + corpid + "&corpsecret=" + corpsecret, JSONObject.class);
        String access_token = (String) forObject.get("access_token");
        redisTemplate.opsForValue().set("OA_TOKEN", access_token, 3600, TimeUnit.SECONDS);
        return access_token;
    }

    public static List<List<String>> groupList(List<String> list) {
        List<List<String>> listGroup = new ArrayList<List<String>>();
        int listSize = list.size();
        //子集合的长度
        int toIndex = 50;
        for (int i = 0; i < list.size(); i += 50) {
            if (i + 50 > listSize) {
                toIndex = listSize - i;
            }
            List<String> newList = list.subList(i, i + toIndex);
            listGroup.add(newList);
        }
        return listGroup;
    }

    //h获取员工的打卡数据
    @Override
    public List<QwCheckinsEntity> getQwCheckinData(int starttimes, int endtime, String[] userids) throws ParseException {
        String oa_token = null;
        if (redisTemplate.opsForValue().get("OA_TOKEN") != null) {
            oa_token = (String) redisTemplate.opsForValue().get("OA_TOKEN");
        } else {
            oa_token = getCheckToktn();
        }
        String url = "https://qyapi.weixin.qq.com/cgi-bin/checkin/getcheckin_daydata?access_token=" + oa_token;
        String checkRecordUrl = "https://qyapi.weixin.qq.com/cgi-bin/checkin/getcheckindata?access_token=" + oa_token;
        HttpHeaders httpHeaders = new HttpHeaders();
        JSONObject jsonObject = new JSONObject();
        if (userids == null) {
            ArrayList<String> list = new ArrayList<>();
            List<QwUserEntity> qwUserEntities = qwUserDao.selectList(null);
            for (QwUserEntity user : qwUserEntities) {
                String userid = user.getUserid();
                list.add(userid);
            }
            if (list.size() > 100) {
                //todo单独考虑
                List<List<String>> lists = groupList(list);
                List<QwCheckinsEntity> qw = new ArrayList<>();
                for (List s : lists) {
                    jsonObject.put("useridlist", s.toArray(new String[s.size()]));
                    List<QwCheckinsEntity> qwCheckinsEntities = getQwCheckinsEntities(starttimes, endtime, url, httpHeaders, jsonObject, checkRecordUrl);
                    for (QwCheckinsEntity q : qwCheckinsEntities) {
                        qw.add(q);
                    }
                }
                return qw;
            } else {
                jsonObject.put("useridlist", list.toArray(new String[list.size()]));
            }
        } else {

            jsonObject.put("useridlist", userids);
        }
        return getQwCheckinsEntities(starttimes, endtime, url, httpHeaders, jsonObject, checkRecordUrl);
    }

    private List<QwCheckinsEntity> getQwCheckinsEntities(int starttimes, int endtime, String url, HttpHeaders httpHeaders, JSONObject jsonObject, String checkRecordUrl) throws ParseException {
            jsonObject.put("starttime", starttimes);
            jsonObject.put("endtime", endtime);
        HttpEntity<JSONObject> httpEntity = new HttpEntity<>(jsonObject, httpHeaders);
        ResponseEntity<JSONObject> responseEntity = restTemplate.postForEntity(url, httpEntity, JSONObject.class);
        // 获取员工的所有打卡记录
        jsonObject.put("opencheckindatatype", 3);
        ResponseEntity<JSONObject> jsonObjectResponseEntity = restTemplate.postForEntity(checkRecordUrl, httpEntity, JSONObject.class);
        JSONObject checkRecord = jsonObjectResponseEntity.getBody();
        JSONArray checkindata = checkRecord.getJSONArray("checkindata");
        ArrayList<CheckRecord> checkRecords = new ArrayList<>();
        for (int c = 0; c < checkindata.size(); c++) {
            HashMap checkinmaMap = JSONObject.parseObject(JSONObject.toJSONString(checkindata.get(c)), HashMap.class);
            if (("外出打卡").equals(checkinmaMap.get("checkin_type"))) {
                //外出打卡
                CheckRecord check_Record = new CheckRecord();
                check_Record.setUserid((String) checkinmaMap.get("userid"));
                check_Record.setCheckin_time((Integer) checkinmaMap.get("checkin_time"));
                checkRecords.add(check_Record);
            }
        }
        JSONObject body = responseEntity.getBody();
        JSONArray datas = body.getJSONArray("datas");
        List<QwCheckinsEntity> qwCheckinsEntities = new ArrayList<>();
        for (int i = 0; i < datas.size(); i++) {
            QwCheckinsEntity qwCheckinsEntity = new QwCheckinsEntity();
            Object o = datas.get(i);
            HashMap map = JSONObject.parseObject(JSONObject.toJSONString(o), HashMap.class);
            Object base_info = map.get("base_info");
            JSONObject jsonObject1 = JSONObject.parseObject(JSONObject.toJSONString(base_info));
            Object sp_items = map.get("sp_items");
            List<HashMap> hashMaps = JSONObject.parseArray(JSONObject.toJSONString(sp_items), HashMap.class);
            // 	类型：1-请假；2-补卡；3-出差；4-外出；100-外勤
            //具体请假类型，当type为1请假时，具体的请假类型id，可通过审批相关接口获取假期详情
            int duration = 0;
            for (HashMap map2 : hashMaps) {
                duration = (int) map2.get("duration");
                if (duration != 0) {
                    //休假
                    qwCheckinsEntity.setDuration(duration);
                    qwCheckinsEntity.setType((Integer) map2.get("type"));
                    qwCheckinsEntity.setVacationId((Integer) map2.get("vacation_id"));
                    // qwCheckinsEntity.setDurationName((String) map2.get("name"));
                    qwCheckinsEntity.setDayType((Integer) jsonObject1.get("day_type"));
                    int date = (int) jsonObject1.get("date");
                    Date date1 = new Date(date * 1000L);
                    qwCheckinsEntity.setWorkDate(date1);
                    break;
                } else {
                    if ((Integer) jsonObject1.get("day_type") == 1) {
                        int date = (int) jsonObject1.get("date");
                        Date date1 = new Date(date * 1000L);
                        qwCheckinsEntity.setDayType((Integer) jsonObject1.get("day_type"));
                        qwCheckinsEntity.setWorkDate(date1);
                        //休假
                    } else {
                        qwCheckinsEntity.setDuration(duration);
                        qwCheckinsEntity.setType((Integer) map2.get("type"));
                   /*     qwCheckinsEntity.setDuration(0);
                        qwCheckinsEntity.setVacationId(0);
                        qwCheckinsEntity.setDurationName("无休假");*/
                        Object summary_info = map.get("summary_info");
                        JSONObject jsonObject2 = JSONObject.parseObject(JSONObject.toJSONString(summary_info));
                        qwCheckinsEntity.setEarliestTime((Integer) jsonObject2.get("earliest_time"));
                        qwCheckinsEntity.setLastestTime((Integer) jsonObject2.get("lastest_time"));
                        qwCheckinsEntity.setName((String) jsonObject1.get("name"));
                        int date = (int) jsonObject1.get("date");
                        Date date1 = new Date(date * 1000L);
                        qwCheckinsEntity.setWorkDate(date1);
                        qwCheckinsEntity.setDayType((Integer) jsonObject1.get("day_type"));
                        qwCheckinsEntity.setUserid((String) jsonObject1.get("acctid"));
                        JSONObject rule_info = JSONObject.parseObject(JSONObject.toJSONString(jsonObject1.get("rule_info")));
                        JSONArray checkintime = rule_info.getJSONArray("checkintime");
                        if (checkintime.size() > 0 && checkintime != null) {
                            String s = checkintime.get(0).toString();
                            JSONObject jsonObject3 = JSON.parseObject(s);
                            int work_sec = Integer.parseInt(jsonObject3.get("work_sec").toString());
                            int off_work_sec = Integer.parseInt(jsonObject3.get("off_work_sec").toString());
                            qwCheckinsEntity.setWorkSec(work_sec);
                            qwCheckinsEntity.setOffWorksec(off_work_sec);
                            // this.save(qwCheckinsEntity);
                            //  qwCheckinsEntities.add(qwCheckinsEntity);
                        }
                        List<CheckRecord> collect = checkRecords.stream().filter(item -> {
                            int checkin_time = item.getCheckin_time();
                            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd : HH:mm:ss");
                            String[] split = sf.format(checkin_time * 1000L).split(":");
                            String[] split1 = sf.format(date1).split(":");
                            return split[0].equals(split1[0]);
                        }).collect(Collectors.toList());
                        if (collect.size() > 0 && collect != null) {
                            if (collect.size() == 1) {
                                //判断是上班还是下班时间
                                CheckRecord checkRecord1 = collect.get(0);
                                int checkin_time = checkRecord1.getCheckin_time();
                                SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd : HH:mm:ss");
                                String[] split = sf.format(checkin_time * 1000L).split(":");
                                String time = split[0] + ": 12:00:00";
                                Date parse = sf.parse(time);
                                int l = (int) parse.getTime() / 1000;
                                if (checkin_time - l > 0) {
                                    //下班时间
                                    qwCheckinsEntity.setLastestTime(collect.get(0).getCheckin_time());
                                } else {
                                    qwCheckinsEntity.setEarliestTime(collect.get(0).getCheckin_time());
                                }
                            } else {
                                int early_time = collect.get(0).getCheckin_time();
                                int late_time = collect.get(1).getCheckin_time();
                                SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd : HH_mm_ss");
                                String[] split = sf.format(early_time * 1000L).split(":");
                                String[] split1 = sf.format(late_time * 1000L).split(":");
                                int zong = getZong(split[1].replace(" ", ""));
                                int zong1 = getZong(split1[1].replace(" ", ""));
                                qwCheckinsEntity.setEarliestTime(zong);
                                qwCheckinsEntity.setLastestTime(zong1);
                            }
                        }
                    }
                }
            }
            qwCheckinsEntities.add(qwCheckinsEntity);
        }
        return qwCheckinsEntities;
    }

    private int getZong(String s) {
        String[] my = s.split("_");
        int hour = Integer.parseInt(my[0]);
        int min = Integer.parseInt(my[1]);
        int sec = Integer.parseInt(my[2]);
        return hour * 3600 + min * 60 + sec;
    }


    /**
     * @return 根据员工的考勤信息生成考情表
     */
    @Override
    public List<Map<String, Object>> getCheckAllTables(int starttimes, int endtime, String[] userids) throws IllegalAccessException, ParseException {
        //拿到每个员工的考勤规则
        List<Map<String, Object>> l = new ArrayList<>();
        List<QwUserEntity> qwUserEntities = new ArrayList<>();
        List<List<String>> allDayTotals = new ArrayList<>();
        if (userids == null) {
            qwUserEntities = qwUserDao.selectList(null);
        } else {
            for (String userid : userids) {
                QwUserEntity qwUserEntity = qwUserDao.selectOne(new QueryWrapper<QwUserEntity>().eq("userid", userid));
                qwUserEntities.add(qwUserEntity);
            }
        }
        for (QwUserEntity qwUserEntity : qwUserEntities) {
            //获得每一个员工的考勤规则id,默认考勤规则为1
            int check_rule_id = qwUserEntity.getCheckRuleId();
            //拿到员工的考勤规则信息
            QwCheckRuleEntity qwCheckRuleEntity = qwCheckRuleDao.selectOne(new QueryWrapper<QwCheckRuleEntity>().eq("groupid", check_rule_id));
           /* int workSec = qwCheckRuleEntity.getWorkSec();
            int offWorkSec = qwCheckRuleEntity.getOffWorkSec();*/
            int overtime = qwCheckRuleEntity.getOvertime();
            int subsidy = qwCheckRuleEntity.getSubsidy(); //餐补金额
            String name1 = qwUserEntity.getName();
            String userid = qwUserEntity.getUserid();
            String[] id = {userid};
            //获取对应员工的考勤信息
            List<QwCheckinsEntity> checkinsEntityList = getQwCheckinData(starttimes, endtime, id);
            ExportQwCheckMonthTableDto exportQwCheckMonthTableDto = new ExportQwCheckMonthTableDto();
            int allSubsidy = 0;
            int overworkday_count = 0;
            int beLate_count = 0;
            int leaveEarly_count = 0;
            for (QwCheckinsEntity qwCheckinsEntity : checkinsEntityList) {
                Date work_date = qwCheckinsEntity.getWorkDate();//获取日期
                Calendar instance = Calendar.getInstance();
                instance.setTime(work_date);
                //获得当天的日
                int workDay = instance.get(Calendar.DAY_OF_MONTH);
                String daysTotal = "";
                if (qwCheckinsEntity.getDayType() == 0) {
                    //判断当天是否存在出差的情况
                    //判断当天是否有请假
                    int type = qwCheckinsEntity.getType();
                    int vacationId = qwCheckinsEntity.getVacationId();
                    if (qwCheckinsEntity.getDuration() > 0 && type == 1) {
                        //todo
                        //存在请假的情况,暂时先按一天整算
                        //获取请假的类型
                        if (type == 1 && vacationId == 1) {
                            daysTotal = "N";
                        }
                        if (type == 1 && vacationId == 2) {
                            daysTotal = "#";
                        }
                        if (type == 1 && vacationId == 3) {
                            daysTotal = "△";
                        }
                        if (type == 1 && vacationId == 4) {
                            daysTotal = "B";
                        }
                        if (type == 1 && vacationId == 5) {
                            daysTotal = "⊙";
                        }
                        if (type == 1 && vacationId == 6) {
                            daysTotal = "V";
                        }
                        if (type == 1 && vacationId == 7) {
                            daysTotal = "Q";
                        }
                        if (type == 1 && vacationId == 8) {
                            daysTotal = "?";
                        }
                    } else if (qwCheckinsEntity.getDuration() > 0 && type != 1) {
                        //从打卡
                    } else {
                        int workSec = qwCheckinsEntity.getWorkSec();
                        int offWorkSec = qwCheckinsEntity.getOffWorksec();

                        //为工作日
                        //是否迟到,1迟到 0未迟到
                        if ((qwCheckinsEntity.getEarliestTime() > workSec ? 1 : 0) == 1) {
                            daysTotal += " " + "≧";
                            beLate_count++;

                        }
                        //是否早退 1.早退 0.未早退
                        if ((qwCheckinsEntity.getLastestTime() < offWorkSec ? 1 : 0) == 1) {
                            daysTotal += " " + "≦";
                            leaveEarly_count++;
                        }
                        //是否存在加班 1.存在加班,有餐补  0.未加班 ,无餐补
                        allSubsidy += (qwCheckinsEntity.getLastestTime() - 64800 > 7200 ? 1 : 0) * subsidy;
                        if (((qwCheckinsEntity.getLastestTime() - offWorkSec) > overtime * 3600 ? 1 : 0) == 1) {
                            daysTotal += " " + "C";
                            overworkday_count++;
                        }
                        //是否缺勤  1. 是缺勤   0. 不缺勤
                        if (qwCheckinsEntity.getEarliestTime() == 0 || qwCheckinsEntity.getEarliestTime() == 0) {
                            daysTotal += " " + "A";
                        }
                    }
                } else {
                    //todo需要判断休息日是否有加班,并且算到休假日的总天数
                    //判断休息日
                    daysTotal = "/";
                }
                //根据每一天的情况,得到一个String  string="value"
                Field[] declaredFields = exportQwCheckMonthTableDto.getClass().getDeclaredFields();
                for (Field f : declaredFields) {
                    f.setAccessible(true);
                    String name = f.getName();
                    String[] s = name.split("_");
                    if (s.length > 1) {
                        int days = Integer.parseInt(s[1]);
                        if (workDay == days) {
                            f.set(exportQwCheckMonthTableDto, daysTotal);
                            Object o = f.get(exportQwCheckMonthTableDto);
                            String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
                            try {
                                Method method = exportQwCheckMonthTableDto.getClass().getDeclaredMethod(methodName, new Class[]{String.class});
                                method.invoke(exportQwCheckMonthTableDto, new Object[]{o});
                            } catch (Exception ex) {
                                ex.printStackTrace();
                            }
                        }
                    }
                }
            }
            exportQwCheckMonthTableDto.setName(name1); //姓名
            exportQwCheckMonthTableDto.setMealsubsidycount(allSubsidy); //加班补贴
            exportQwCheckMonthTableDto.setMealsubsidydays(overworkday_count); //加班天数
            exportQwCheckMonthTableDto.setWorkday(checkinsEntityList.stream().filter((item) -> {
                return (item.getDayType() == 0);
            }).collect(Collectors.toList()).size()); //出勤日
            exportQwCheckMonthTableDto.setPersonalleavecount(checkinsEntityList.stream().filter((item) -> {
                return (item.getType() == 1 && item.getVacationId() == 2);
            }).collect(Collectors.toList()).size()); //事假
            exportQwCheckMonthTableDto.setSickLeavecount(checkinsEntityList.stream().filter((item) -> {
                return (item.getType() == 1 && item.getVacationId() == 3);
            }).collect(Collectors.toList()).size()); //病假
            exportQwCheckMonthTableDto.setAnnualleavecount(checkinsEntityList.stream().filter((item) -> {
                return (item.getType() == 1 && item.getVacationId() == 1);
            }).collect(Collectors.toList()).size()); //年假
            exportQwCheckMonthTableDto.setDayoffcount(checkinsEntityList.stream().filter((item) -> {
                return (item.getType() == 1 && item.getVacationId() == 4);
            }).collect(Collectors.toList()).size()); //调休
            exportQwCheckMonthTableDto.setMaternityleavecount(checkinsEntityList.stream().filter((item) -> {
                return (item.getType() == 1 && item.getVacationId() == 6);
            }).collect(Collectors.toList()).size()); //产假
            exportQwCheckMonthTableDto.setPaternityeavecount(checkinsEntityList.stream().filter((item) -> {
                return (item.getType() == 1 && item.getVacationId() == 7);
            }).collect(Collectors.toList()).size()); //陪产假
            exportQwCheckMonthTableDto.setElseleave(checkinsEntityList.stream().filter((item) -> {
                return (item.getType() == 1 && item.getVacationId() == 8);
            }).collect(Collectors.toList()).size()); //其他
            exportQwCheckMonthTableDto.setAbsencecount(checkinsEntityList.stream().filter((item) -> {
                return (item.getEarliestTime() == 0 || item.getEarliestTime() == 0);
            }).collect(Collectors.toList()).size()); //未打卡
            exportQwCheckMonthTableDto.setBelatecount(beLate_count); //迟到
            exportQwCheckMonthTableDto.setSickLeaveearly(leaveEarly_count); //早退
            Map<String, Object> map = JSONObject.parseObject(JSON.toJSONString(exportQwCheckMonthTableDto), Map.class);
            l.add(map);
        }
        /*    qwCheckTotalVo.setList(list);
            l.add(qwCheckTotalVo);*/
        return l;
    }


    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<QwCheckinsEntity> page = this.page(
                new Query<QwCheckinsEntity>().getPage(params),
                new QueryWrapper<QwCheckinsEntity>()
        );
        return new PageUtils(page);
    }

}